﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Remoting;
using System.Security.Permissions;
using System.Web.UI.WebControls.WebParts;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebPartPages;
using EF;

namespace test
{
    class Program
    {
        public static string AddWebPartPage(string strFileName, string strFileTitle, SPWeb objSPWeb, SPList objSPList, int iWebPartPageTemplate, string strPageType, string strFolderPath)
        {
            SPFile objSPFile = null;
            string postInformation =
            @"<?xml version=""1.0"" encoding=""UTF-8""?>" +
            @"<Method>" +
            @"<SetList Scope=""Request"">" + objSPList.ID + @"</SetList>" +
            @"<SetVar Name=""ID"">New</SetVar>" +
            @"<SetVar Name=""Cmd"">NewWebPage</SetVar>" +
            @"<SetVar Name=""Type"">" + strPageType + @"</SetVar>" +
            @"<SetVar Name=""WebPartPageTemplate"">" + iWebPartPageTemplate + @"</SetVar>" +
            @"<SetVar Name=""Title"">" + strFileName + @"</SetVar>" +
            @"<SetVar Name=""Overwrite"">true</SetVar>" +
            @"</Method>";
            string processBatch = objSPWeb.ProcessBatchData(postInformation);
            if (processBatch.Equals("<Result ID=\"\" Code=\"0\">\r\n</Result>\n", StringComparison.InvariantCultureIgnoreCase))
            {
                string strFileUrl = objSPList.RootFolder.Url + "/" + strFileName;
                if (strFileUrl.EndsWith(".aspx") == false)
                {
                    strFileUrl += ".aspx";
                }
                objSPFile = objSPWeb.GetFile(strFileUrl);
                //if page was in subfolder then move it there
                if (!String.IsNullOrEmpty(strFolderPath))
                {
                    objSPFile.MoveTo(strFileTitle, true);
                }
                SPFolder rootFolder = objSPFile.ParentFolder;

                using (SPLimitedWebPartManager spLimitedWebPartManager = objSPWeb.GetLimitedWebPartManager(strFileUrl, PersonalizationScope.Shared))
                {

                    foreach (System.Web.UI.WebControls.WebParts.WebPart objWebpart in spLimitedWebPartManager.WebParts)
                    {
                        if (objWebpart.ToString() == "Microsoft.SharePoint.WebPartPages.TitleBarWebPart")
                        {
                            TitleBarWebPart objTitleBarWebPart = (TitleBarWebPart)objWebpart;
                            objTitleBarWebPart.HeaderTitle = strFileTitle;
                            spLimitedWebPartManager.SaveChanges(objTitleBarWebPart);
                            break;
                        }
                    }
                    //System.Web.UI.WebControls.WebParts.WebPart objWebPart = spLimitedWebPartManager.WebParts["TitleBar"];
                    //objWebPart.Title = strFileTitle;
                    objSPWeb.Update();
                }

                return objSPFile.Url;
            }

            return string.Empty;
        }

        public static System.Web.UI.WebControls.WebParts.WebPart CreateWebPart(SPWeb web, string webPartName)
        {
            SPQuery query = new SPQuery();
            query.Query = String.Format(
                "<Where><Eq><FieldRef Name='FileLeafRef'/><Value Type='File'>{0}</Value></Eq></Where>",
                webPartName);

            SPList webPartGallery = null;

            if (null == web.ParentWeb)
            {
                // This is the root web.
                webPartGallery = web.GetCatalog(SPListTemplateType.WebPartCatalog);
            }
            else
            {
                // This is a sub-web.
                webPartGallery = web.ParentWeb.GetCatalog(SPListTemplateType.WebPartCatalog);
            }

            SPListItemCollection webParts = webPartGallery.GetItems(query);

            string typeName = webParts[0].GetFormattedValue("WebPartTypeName");
            string assemblyName = webParts[0].GetFormattedValue("WebPartAssembly");
            ObjectHandle webPartHandle = Activator.CreateInstance(assemblyName, typeName);

            System.Web.UI.WebControls.WebParts.WebPart webPart =
                (System.Web.UI.WebControls.WebParts.WebPart)webPartHandle.Unwrap();
            return webPart;
        }

        public static object ConvertValue(string propertyValue, PropertyInfo property)
        {
            if (propertyValue != string.Empty)
            {
                object value = Convert.ChangeType(propertyValue, property.PropertyType);
                return value;
            }

            return null;
        }

        public static void SetWebPartProperty(
            SPWeb web,
            string pageUrl,
            string webPartID,
            string propertyName,
            string propertyValue)
        {
            using (SPLimitedWebPartManager manager = web.GetLimitedWebPartManager(pageUrl, PersonalizationScope.Shared))
            {
                System.Web.UI.WebControls.WebParts.WebPart part = manager.WebParts[webPartID];
                Type runtimeType = part.GetType();
                PropertyInfo property = runtimeType.GetProperty(propertyName);
                object value = ConvertValue(propertyValue, property);
                property.SetValue(part, value, null);
                manager.SaveChanges(part);
            }
        }

        public static void AddWebPartConnection(
            SPWeb web,
            string pageUrl,
            string providerWebPartID,
            string consumerWebPartID,
            string providerConnectionPointName,
            string consumerConnectionPointName)
        {
            using (SPLimitedWebPartManager manager = web.GetLimitedWebPartManager(pageUrl, PersonalizationScope.Shared))
            {
                System.Web.UI.WebControls.WebParts.WebPart provider = manager.WebParts[providerWebPartID];
                System.Web.UI.WebControls.WebParts.WebPart consumer = manager.WebParts[consumerWebPartID];

                ProviderConnectionPointCollection providerPoints = manager.GetProviderConnectionPoints(provider);
                ConsumerConnectionPointCollection consumerPoints = manager.GetConsumerConnectionPoints(consumer);

                ProviderConnectionPoint providerPoint = null;

                foreach (ProviderConnectionPoint point in providerPoints)
                {
                    if (String.Equals(providerConnectionPointName, point.DisplayName, StringComparison.OrdinalIgnoreCase))
                    {
                        providerPoint = point;
                        break;
                    }
                }

                ConsumerConnectionPoint consumerPoint = null;

                foreach (ConsumerConnectionPoint point in consumerPoints)
                {
                    if (String.Equals(consumerConnectionPointName, point.DisplayName, StringComparison.OrdinalIgnoreCase))
                    {
                        consumerPoint = point;
                        break;
                    }
                }

                manager.SPConnectWebParts(provider, providerPoint, consumer, consumerPoint);
            }
        }

        public static void initAdminPage(SPSite site)
        {
            SPDocumentLibrary spDocPageLib = null;

            SPWeb objSPWeb = site.RootWeb;
            Guid guidSitePages = Guid.Empty;
            SPList objSPList = objSPWeb.Lists.TryGetList(EFWorkflowTimer.DocLib_SitePages_Title);
            if (objSPList == null)
            {
                guidSitePages = objSPWeb.Lists.Add(EFWorkflowTimer.DocLib_SitePages_PathName, "EF WorkflowTimer Page library", SPListTemplateType.DocumentLibrary);
            }
            else
            {
                guidSitePages = objSPList.ID;
                foreach (SPListItem item in objSPList.Items)
                {
                    if (item.File.Name.StartsWith(EFWorkflowTimer.AdminPage_Name, StringComparison.InvariantCultureIgnoreCase))
                    {
                        item.Delete();
                        break;
                    }
                }
            }
            spDocPageLib = (SPDocumentLibrary)objSPWeb.Lists[guidSitePages];

            string strPageUrl = AddWebPartPage(EFWorkflowTimer.AdminPage_Name, "EF WorkflowTimer Admin Page", objSPWeb, spDocPageLib, 2, "WebPartPage", "");

            string strListUrl = string.Empty;
            ListViewWebPart objListViewWebPart = null;
            SPLimitedWebPartManager manager = null;

            try
            {
                //strListUrl = objSPWeb.Url + EFWorkflowTimer.Configuration_ListUrl;
                objSPList = objSPWeb.Lists.TryGetList(EFWorkflowTimer.Configuration_ListTitle);
                if (objSPList == null)
                    throw new ArgumentException("Configuration List(" + EFWorkflowTimer.Configuration_ListTitle + ") not found.");
                objListViewWebPart = AddListViewToPage(objSPWeb, strPageUrl, objSPList.DefaultView, EFWorkflowTimer.Zone_LeftColumn, 1, @"Scheduled Workflow list");

                //strListUrl = objSPWeb.Url + EFWorkflowTimer.History_ListUrl;
                objSPList = objSPWeb.Lists.TryGetList(EFWorkflowTimer.History_ListTitle);
                if (objSPList == null)
                    throw new ArgumentException("History List(" + EFWorkflowTimer.History_ListTitle + ") not found.");
                AddListViewToPage(objSPWeb, strPageUrl, objSPList.DefaultView, EFWorkflowTimer.Zone_Footer, 1, string.Empty);

                objSPList = objSPWeb.Lists.TryGetList(EFWorkflowTimer.Job_ListTitle);
                if (objSPList == null)
                    throw new ArgumentException("Job List(" + EFWorkflowTimer.Job_ListTitle + ") not found.");
                Console.WriteLine(string.Format(@"JobView.Title={0}, JobView.Url={1}", objSPList.Views[EFWorkflowTimer.View_Portal].Title, objSPList.Views[EFWorkflowTimer.View_Portal].Url));

                SPView objCurrent = objSPList.Views[EFWorkflowTimer.View_Portal];
                AddListViewToPage(objSPWeb, strPageUrl, objCurrent, EFWorkflowTimer.Zone_RightColumn, 1, string.Empty);

            }
            catch (Exception ex)
            {
                Console.WriteLine(string.Format(@"ex.Message={0}", ex.Message));
                Console.WriteLine(string.Format(@"ex.StackTrace={0}", ex.StackTrace));

                throw;
            }
        }

        //  http://neganov.blogspot.com/2007/11/add-web-part-to-sharepoint-page.html
        public static ListViewWebPart AddListViewToPage(
            SPWeb objSPWeb,
            string pageUrl,
            SPView objSPView,
            string zoneID,
            int zoneIndex,
            string strWebPartTitle)
        {
            ListViewWebPart objListViewWebPart = null;
            string strListUrl = string.Empty;
            string strListViewWebPartID = string.Empty;
            if (string.IsNullOrEmpty(strWebPartTitle))
                strWebPartTitle = objSPView.ParentList.Title;

            using (SPLimitedWebPartManager spLimitedWebPartManager = objSPWeb.GetLimitedWebPartManager(pageUrl, PersonalizationScope.Shared))
            {
                using (objListViewWebPart = new ListViewWebPart())
                {
                    objListViewWebPart.ListName = objSPView.ParentList.ID.ToString("B").ToUpperInvariant();
                    objListViewWebPart.TitleUrl = objSPView.ServerRelativeUrl;
                    objListViewWebPart.WebId = objSPWeb.ID;
                    objListViewWebPart.Title = strWebPartTitle;
                    objListViewWebPart.ViewGuid = objSPView.ID.ToString();
                    //objListViewWebPart.DisplayTitle = "abcdefg";

                    spLimitedWebPartManager.AddWebPart(objListViewWebPart, zoneID, zoneIndex);

                    foreach (System.Web.UI.WebControls.WebParts.WebPart objWebpart in spLimitedWebPartManager.WebParts)
                    {
                        if (objWebpart.TitleUrl == objSPView.ServerRelativeUrl)
                        {
                            return (ListViewWebPart)objWebpart;
                        }
                    }
                }

                //return strListViewWebPartID;
                return null;
            }
        }

        public static void initLists(SPSite site)
        {
            SPList splistConfiguration = null;
            SPList splistHistory = null;

            SPView oViewConfiguration = null;
            SPViewFieldCollection oViewFieldsConfiguration = null;

            SPView oViewHistory = null;
            SPViewFieldCollection oViewFieldsHistory = null;

            try
            {
                splistConfiguration = site.RootWeb.Lists.TryGetList(EFWorkflowTimer.Configuration_ListTitle);
                if (splistConfiguration == null)
                {
                    Guid guidConfiguration = site.RootWeb.Lists.Add(EFWorkflowTimer.Configuration_ListTitle, EFWorkflowTimer.Configuration_ListDescription, SPListTemplateType.GenericList);
                    splistConfiguration = site.RootWeb.Lists[guidConfiguration];
                    splistConfiguration.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowType, SPFieldType.Choice, true);
                    splistConfiguration.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowName, SPFieldType.Choice, true);
                    splistConfiguration.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_ViewUrl, SPFieldType.Text, true);
                    SPFieldChoice objSPFieldNotificationType = (SPFieldChoice)splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowType];
                    objSPFieldNotificationType.Choices.Add(EFWorkflowTimer.WorkflowType_Site);
                    objSPFieldNotificationType.Choices.Add(EFWorkflowTimer.WorkflowType_List);
                    objSPFieldNotificationType.DefaultValue = EFWorkflowTimer.WorkflowType_Site;
                    objSPFieldNotificationType.Update();
                    splistConfiguration.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_LastScanTime, SPFieldType.DateTime, false);
                    SPFieldDateTime objSPFieldLastScanTime = (SPFieldDateTime)splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_LastScanTime];
                    objSPFieldLastScanTime.DisplayFormat = SPDateTimeFieldFormatType.DateTime;
                    objSPFieldLastScanTime.Update();
                    splistConfiguration.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerCfg_LastScanCount, SPFieldType.Number, false);
                    //splistConfiguration.Fields[EFWorkflowTimer.Column_Title].Required = false;
                    //splistConfiguration.Fields[EFWorkflowTimer.Column_Title].Update();

                    splistConfiguration.Update();

                    oViewConfiguration = splistConfiguration.DefaultView;
                    oViewFieldsConfiguration = oViewConfiguration.ViewFields;
                    oViewFieldsConfiguration.Add(splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowType]);
                    oViewFieldsConfiguration.Add(splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowName]);
                    oViewFieldsConfiguration.Add(splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_ViewUrl]);
                    oViewFieldsConfiguration.Add(splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_LastScanTime]);
                    oViewFieldsConfiguration.Add(splistConfiguration.Fields[EFWorkflowTimer.Column_EFWorkflowTimerCfg_LastScanCount]);

                    oViewConfiguration.Update();

                    //add test data
                    SPListItem itemConfiguration = splistConfiguration.AddItem();
                    itemConfiguration[SPBuiltInFieldId.Title] = @"EFWorkflowTimer test";
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowType] = EFWorkflowTimer.WorkflowType_Site;
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowName] = @"SiteWorkflow1";
                    itemConfiguration.Update();

                    itemConfiguration = splistConfiguration.AddItem();
                    itemConfiguration[SPBuiltInFieldId.Title] = @"EFWorkflowTimer test";
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowType] = EFWorkflowTimer.WorkflowType_List;
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_WorkflowName] = @"ListWorkflow1";
                    itemConfiguration[EFWorkflowTimer.Column_EFWorkflowTimerCfg_ViewUrl] = @"/Lists/testTimer/AllItems.aspx";
                    itemConfiguration.Update();
                }

                //make sure the history list is already created
                splistHistory = site.RootWeb.Lists.TryGetList(EFWorkflowTimer.History_ListTitle);
                if (splistHistory != null)
                    splistHistory.Delete();

                Guid guidHistory = site.RootWeb.Lists.Add(EFWorkflowTimer.History_ListTitle, EFWorkflowTimer.History_ListDescription, SPListTemplateType.GenericList);
                splistHistory = site.RootWeb.Lists[guidHistory];
                //splistHistory.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerHistory_WorkflowType, SPFieldType.Text, false);
                //splistHistory.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerHistory_WorkflowName, SPFieldType.Text, false);
                splistHistory.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerHistory_WebTitle, SPFieldType.Note, false);
                SPFieldMultiLineText objSPFieldWebTitle = (SPFieldMultiLineText)splistHistory.Fields[EFWorkflowTimer.Column_EFWorkflowTimerHistory_WebTitle];
                objSPFieldWebTitle.RichText = false;
                objSPFieldWebTitle.RichTextMode = SPRichTextMode.Compatible;
                objSPFieldWebTitle.Update();
                splistHistory.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerHistory_WebUrl, SPFieldType.Text, false);
                splistHistory.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerHistory_ListTitle, SPFieldType.Text, false);
                splistHistory.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerHistory_ItemId, SPFieldType.Number, false);
                splistHistory.Fields.Add(EFWorkflowTimer.Column_EFWorkflowTimerHistory_ItemUrl, SPFieldType.Text, false);
                splistHistory.Fields[SPBuiltInFieldId.Title].Required = false;
                splistHistory.Fields[SPBuiltInFieldId.Title].Update();

                oViewHistory = splistHistory.DefaultView;
                oViewFieldsHistory = oViewHistory.ViewFields;
                oViewFieldsHistory.Add(splistHistory.Fields[SPBuiltInFieldId.Modified].InternalName);
                oViewFieldsHistory.Add(splistHistory.Fields[SPBuiltInFieldId.Title].InternalName);
                //oViewFieldsHistory.Add(splistHistory.Fields[EFWorkflowTimer.Column_EFWorkflowTimerHistory_WorkflowType]);
                //oViewFieldsHistory.Add(splistHistory.Fields[EFWorkflowTimer.Column_EFWorkflowTimerHistory_WorkflowName]);
                oViewFieldsHistory.Add(splistHistory.Fields[EFWorkflowTimer.Column_EFWorkflowTimerHistory_WebTitle]);
                oViewFieldsHistory.Add(splistHistory.Fields[EFWorkflowTimer.Column_EFWorkflowTimerHistory_ListTitle]);
                oViewFieldsHistory.Add(splistHistory.Fields[EFWorkflowTimer.Column_EFWorkflowTimerHistory_ItemUrl]);
                //oViewFieldsHistory.Add(splistHistory.Fields[EFWorkflowTimer.Column_EFWorkflowTimerHistory_Modified]);
                oViewHistory.Query = @"<OrderBy><FieldRef Name='ID' Ascending='FALSE' /></OrderBy>";
                oViewHistory.Update();
            }
            catch (Exception ex)
            {
                Console.WriteLine(string.Format(@"ex.Message={0}", ex.Message));
                Console.WriteLine(string.Format(@"ex.StackTrace={0}", ex.StackTrace));

                Console.ReadLine();
            }
        }

        static void Main(string[] args)
        {
            using (SPSite objSPSite = new SPSite(@"http://hvsp2010a:8080"))
            {
                //initLists(objSPSite);

                using (SPWeb objSPWeb = objSPSite.OpenWeb())
                {
                    //delete admin page
                    Guid guidSitePages = Guid.Empty;
                    SPList objSPList = objSPWeb.Lists.TryGetList(EFWorkflowTimer.DocLib_SitePages_Title);
                    if (objSPList != null)
                    {
                        guidSitePages = objSPList.ID;
                        foreach (SPListItem item in objSPList.Items)
                        {
                            if (item.File.Name.StartsWith(EFWorkflowTimer.AdminPage_Name, StringComparison.InvariantCultureIgnoreCase))
                            {
                                item.Delete();
                                break;
                            }
                        }
                    }
                    Console.WriteLine("Admin page deleted.");

                    initAdminPage(objSPSite);

                    Console.WriteLine("Completed. Press enter key to exit.");
                    Console.ReadLine();
                }
            }

        }
    }
}
